Getting Started Popular Psions Howard Oakley EHN & DIJ Oakley Howard@quercus.demon.co.uk COPYRIGHT(C) 1994 BY CREATIVE DIGITAL SYSTEMS. ALL RIGHTS RESERVED. A few weeks after the hullabaloo of Apple's launch of the Newton, in September 1993, a relatively small British firm launched a new and much improved version of their palmtop computer, which has already outsold Newton several times over. The Series 3a, from Psion, lacks much of the glamour of the Newton, using a miniature keyboard rather than handwriting recognition, a derivative of the 8088 processor rather than an exotic RISC chip, and what amounts to a built-in Basic rather than innovative NewtonScript. But pitched against the same consumer electronics market, Psion has been selling 24,000 units a month, and is popular in both the US and Europe, while Apple's much-opined product has been struggling to sell 100,000 units worldwide. [Psion recently launched an aggressive radio advertising campaign in the Bay Area. Ed.] Changes in direction in the marketing of Newton are also having profound effects. After stunning initial sales of the Newton Toolkit (NTK), and several dozen horizontal commercial software releases, Apple is refocusing on vertical and in-house corporate markets. If you have been slaving away in the hope that your first Newton application will be a runaway success, you might by now be worrying whether it will even make it as shareware. By contrast, there are little more than a dozen commercial applications for the Series 3a, and surprisingly few developers aiming to swell that number. This extended review is intended to assess Psion's product and support available to develop for it. Does it make sense for a Newton developer to consider adding Psion products to their portfolio, or even switch completely to Series 3a development? The Psion Series 3a A compact (6.5 x 3.3 x 0.9 inches) charcoal gray case opens to reveal three major functional areas: a small but high-quality retardation film LCD screen which provides 480 x 160 pixels, and a miniature 58-key QWERTY keyboard which avoids the common calculator feature of overassigning key functions with multiple modifiers. Bridging the screen and keyboard, and spanning the inside of the spine of the case, is a strip containing eight touch-sensitive navigational icons. The screen resolution is sufficient to enable 17 lines of 80 column text to be viewed in good conditions. This is assisted by a range of standard font sizes from 6 to 14 points, and Zoom In and Out commands in the applications. Psion 3a graphics use an ingenious two-plane system, with black and white and gray layers. The end result of adding a true, rather than dithered, gray-scale plane is extremely attractive and is a considerable enhancement to the interface. [Unfortunately, we were not able to adequately capture the two-level images in our screen shots. Ed.] The bottom right-hand edge of the unit conceals a small integral microphone, while a larger loudspeaker is built into the back of the keyboard half of the unit. There are two AA batteries which afford legendary life (measured in months rather than hours), and two hidden slots for Psion's compact, proprietary SSD memory disks. The whole assembly is robust and benefits from extensive experience producing handheld devices which can withstand the common insults of the environment: there are numerous accounts of Psion products, including the 3a, surviving falls, drops, and adverse applications of water. Internally, the Series 3a is a direct descendent of the earliest calculator-style Organiser. The processor is an ASIC-embedded NEC V30, essentially a 16-bit version of the venerable 8088, running at 7.7 MHz. It is set into a design known as SIBO (SIngle Board Organiser), which is common to Psion's vertical market HC series products, but implemented around a single custom chip. Among the many enhancements between the HC and 3a hardware is support for digital sound in the latter. This allows for sophisticated alarms and reliable DTMF phone dialing. Two 3a models are currently shipping: one with 256 KB of built-in memory (list price $495), the other with 512 KB (list $595). They are otherwise identical, except that the smaller model is unlikely to satisfy the demands of either the developer or those who use their 3as extensively. The larger model, coupled with a storage card or two, is more than adequate even for the most demanding, owing to the operating system and applications' parsimonious use of memory. Internal memory is used for both the modest runtime requirements of applications and system software, and functions as storage (although installed SSD cards only provide storage). ROM is a modest 1 MByte, which is sufficient to contain the seven major built-in applications, plus a handful of utilities, the OPL (Basic-like) program translator and interpreter, and nearly two-hundred programmer-accessible object-oriented classes ranging from the interface elements to the filing system. The operating system is EPOC (for once, not an acronym but a contraction of "epoch", which denotes its significance to Psion), a preemptive, multitasking kernel with a file system superficially similar to MS-DOS, with familiar "8.3" character names. Indeed, on RAM devices, it even uses the same file allocation table (FAT), although for Flash devices Psion worked with Microsoft to develop a suitable alternative. However, EPOC is sufficiently unobtrusive such that those who restrict themselves to using the built-in and other commercial applications should not notice any formal operating system. In Use Although the OS underpinnings may be reminiscent of what MS-DOS might have been, the veneer seen by most users is far more friendly. The major built-in applications - a card index of names and addresses, a word-processor capable of long styled documents, the delightful Agenda diary (see Figure 1), a remarkably bug-free alarm system, a type-in calculator, and a powerful spreadsheet (see Figure 2) - can be brought to the front by the touch-sensitive applications bar. Applications and their documents can be launched from icons and labels in a horizontally-scrolling desktop strip which represents the System (see Figure 3 on the next page). Each installed application is represented there by its icon, below which are listed the documents available to that application. When you highlight a document name and press the Enter key, that document is opened in its application. A practical touch is the ability to group applications and documents into what are effectively analogous to Macintosh folders (see Figure 4), although documents never float loose from their applications. Given the small screen real estate, Psion has wisely hidden menus from default System and application views. Instead, menus, which have extensive command key equivalents, pop up when you press a special Menu key (see Figure 5). For a Mac or Windows user, these keyboard shortcuts may seem confusing: Psion-C is still "copy" and Psion-S "save" but "paste" is Psion-I (insert) and "quit" is Psion-X (exit). Similarly, the arrangement of menus is not always as consistent between built-in applications as on the Mac. It comes as some surprise, for instance, to discover the word count command in the word processor's Search menu. The individual 3a applications are complete and unlikely to leave you wanting more. The only significant omission is a spelling checker and thesaurus for the word processor (these are available as a separate $100 product from Psion). Printing support is not uniformly good -accessory packs enable direct connection to serial and parallel printers (serial $25, parallel $60), which can use Postscript when it's available. However, working with a networked printer such as a LaserWriter is clumsy: you have to print to a disk file, transfer the file back to a host desktop computer, then download the Postscript file using a utility. The most obvious feature missing from all applications is the ability to draw or sketch. The Series 3a is text (and number) bound, and graphics are something to be displayed (see Figure 6) rather than edited and manipulated by the user. A brave shareware effort at implementing drawing by means of editing bitmaps demonstrates just how frustrating it is trying to paint with cursor keys. Compare the Newton's ever-present ability to sketch, and the richness that injects to notes and applications. Connectivity and Expansion There are only two external connections available on a Series 3a (in addition to the two SSD bays). One is for the main AC adaptor, a $20 optional accessory that is specific to one of the two major supply types rather than being a worldwide universal unit. The other is a nonstandard six-pin rectangular port into which proprietary serial and parallel adapters (Psion, $25 to $120) fit. Although the specification for this connection claims 1.5 Mbps throughput, interfacing to other systems requires a "soap bar" adaptor which works at more pedestrian baud rates and encumbers the traveler with additional equipment. Connection to desktop systems for file transfer and backup is also not as easy as it should be (although Psion is working hard to improve this). The traditional mainstay is McLink, a command-driven utility available for the Mac and PC (MS-DOS), but this is being progressively superseded by more friendly GUI-based programs such as RComm (currently in beta) for Windows, and Psion Link for Macintosh (supplied with the Mac Serial Link, $120 complete). There are still problems with single-command backup to the Mac, though, which does not work when Mac file-sharing is enabled. File translations are done by saving files from within applications in the required format, not through the connection software. Although modem communications can be made using almost any modem with a serial interface, and there is a basic communications application provided in ROM, faxing is more complex. The only software available to support fax transmission is bundled with the only fax-modem which it supports, the Psion 3Fax, an external Psion model which is excellent but fairly expensive ($400) compared to mass market desktop fax-modems. Although the fax-modem requires a Series 3a with 512 K of memory, it does not support receiving faxes. Further, since the Psions do not have PCMCIA slots, you cannot use any compact card fax-modems. That having been said, the 3Fax external fax-modem and software is a wonderful product which works much better and more quickly than those available for desktop systems. This highlights one of the biggest problems with expansion -Psion's avoidance of PCMCIA in preference to its own SSD standard. A complete two-page appendix in the development manuals is devoted to a justification of this decision. While it has undoubtedly enabled Psion to keep the size of the HC, 3 and 3a series small while still offering two slots in the latter two devices, several of the arguments made do not any longer hold water. Psion claims that SSDs will remain cheaper than PCMCIA equivalents, although the rise in popularity of the latter has now resulted in the reverse being the case (a Psion 2 MByte Flash SSD retails for $550). They also claim that the idea of a "universal" PCMCIA standard permitting exchange of data by card is illusory. Although the Newton has already shown this to be true, compatibility is sufficient to ensure that the PCMCIA market is large enough to bring prices down. SSDs therefore remain a mixed blessing. Another oddity of Psion's Flash (not SRAM) SSDs is that deleted files are not returned to free "disk" space until the SSD is reformatted. Thus, in use, Flash SSDs suffer a steady reduction in free space until they become exhausted, at which time you have to back them up, reformat the SSD, and then restore the active contents. This saves Flash SSDs from having complex drivers which ensure that different areas of memory are used in sequence to even out their eventual failure, but it is not as friendly. There is the hope that the progressive introduction of Type 2 Flash SSDs will solve this, but it is uncertain when partial reformatting will actually be widespread. Development Tools There are no fewer than six development choices for the Series 3 and 3a. Built into every machine, and documented in the user manuals, is a Basic-like language, OPL (Organiser Programming Language). Although Psion supplies a PC-hosted OPL development kit, this is primarily intended for use with their HC series systems, which lack a built-in version of OPL. Those porting C code from other platforms can use either the CLIB or PLIB libraries if they require a standard console use interface. Although these two libraries can be mixed, PLIB produces tighter applications which are more closely matched to the EPOC System software architecture; CLIB I/O is restricted to getchar and puts. Next in order of increasing sophistication is the WLib interface, which lets you use graphics output, better keyboard input, fonts, and windows, resulting in applications which are similar in their user interface to many of those produced using OPL. Until this year, the best access to the ROM was provided by HWIF (Handheld Wimp InterFace), in which C code calls an extensive library providing sophisticated printing, menus, dialogs and edit boxes. These match - and on occasion surpass - the very best interface achievable using OPL. Most recently, Psion has documented and supported third party development with its own in-house development library, based on an object-oriented (OO) toolkit. Rather than use a standard OO language such as C++, they chose to modify C in a manner which can best be described as improvised. Although this choice gives you access to a huge and potent class library, it may seem ungainly if you're used to working with other systems which use OO languages. [For more details on the components provided in Psion's different developer kits, see "Psion Series 3 Software Development" on page 26.] Another important issue in planning future development is of course the quality and availability of support, both technical and that for end users. You can rest assured that Psion staff are readily accessible, and take great delight in supporting their products as fully as they possibly can. Psion does not have any policies which limit information available to developers - whether registered or not - and staff frequently devote considerable time in developing illustrative code, or in describing the little that has not yet been comprehensively documented. Regular visitors to online support areas such as that on CompuServe include those who wrote the 3a ROM, ensuring absolute authority. Operating System Internals The EPOC operating system is conventional in many respects, such as the filing system, although its multitasking and asynchronous I/O put it in a different league from the likes of MS-DOS. The filing system greeting the developer (and power users) uses volumes distinguished by letters, and features an extensive system of directories and file name extensions. One interesting addition to this is the use of prefatory device paths, with "LOC::" specifying a local and "REM::" a remote device. Although in everyday use the ordinary 3a user is unaware, applications have very specific fixed search paths for files. For instance, the word processor expects to find all its documents in the "\WRD" directory of mounted volumes, and getting it to read a file in another directory is relatively complex. Normally applications use hidden three character file name extensions to indicate the format of individual files ( for instance, a .WRD file is in word processor native format). As you might expect from a palmtop computer with an alarm system, the 3a is never actually powered down in normal use, but put to sleep. When this happens (after a period of disuse or by user command), the alarm clock and any other running applications remain so. During sleep the screen is turned off and the CPU speed dropped, permitting slow processing such as processes as alarm timers. The device is reawakened programmatically by the expiration of an absolute timer or by user command. There is extensive system support for ISAM (Indexed Sequential Access Method) database files. These use B-tree index files to great effect, and access is available from both OPL and C, the latter via a dynamic library. Field types supported include a range of signed and unsigned one, two and four-byte data types, as well as doubles and strings. The maximum number of records that can be accessed through the PLIB library is 65,534, and there is an overall maximum key size of 64 bytes. Up to 31 index files can be open at a time. A potential limitation to the use of ISAM is that index files that change should not be stored on a Flash SSD (RRAM SSD is not a problem) because of the lack of support for the automatic reuse of Flash memory. Practical experience suggests that this is of little real consequence, though. OPL - A Basic-like Language The great majority of 3a programs are written using the built-in, Basic-like interpreted language OPL (Organiser Programming Language), developed by Psion for their early Organiser products. OPL gives surprisingly good access to System facilities without resorting to constructions such as PEEK and POKE, and there are sensible extensions which allow an OPL programmer to call on many of the rich features of the ROM. The performance and effectiveness of OPL is witnessed by the fact that it remains the road of choice for the majority of commercial developers for Psion's products. It is inevitably very popular among those who write code for their own use, or for free and shareware distribution, but you might be surprised at the number of commercial applications which have been written primarily in OPL. One word of caution -there is a freeware reverse translator, Revtran written by Mike Rudin, which can generate OPL source code from translated OPL files. You might like to implement a scheme to prevent reverse translation of commercial products, or code the more proprietary sections in C. Although it is enhanced, OPL is still at heart Basic. It has neither FOR...NEXT... loops, nor a CASE construct, although VECTOR, essentially a computed GOTO, comes close to the latter: VECTOR J% REM depending on the integer value FUNCA, FUNCB, REM of J%GOTO of of these labels FUNCC ENDV REM end VECTOR REM this is where the code ends up if J% < 1 or J% > 3 FUNCA:: REM a label REM this is for J% = 1 FUNCB:: REM this is for J% = 2 FUNCC:: REM this is for J% = 3 Modules are supported with the LOAD and UNLOAD commands, procedures can be called using their string names and procedure caching can be controlled with sophistication. Runtime errors in most common I/O commands can be handled by a TRAP mechanism, and there is a generally applicable ONERR invocation of an error handler. The default translation of OPL programs (see Figure 6) results in executables which are run using the built-in RunOPL utility. However, more polished results can be produced by turning a translated program into an OPA (OPL Application) file. This requires slight modification of the source code with an APP code block such as the following: APP Piedemo TYPE $1003 REM this declares it as an OPA of Type 3, REM which can have more than one file open REM at a time, like the built-in word processor; REM also that it has its own 48x48 pixel, REM two-plane icon PATH "\PIE" REM set the default directory for files EXT "PIE" REM sets the default file extension ICON "\OPD\PIE.PIC" REM sets the icon file ENDA Unlike ordinary OPL programs, OPA applications are expected to contain some form of event loop in order to handle key presses and other System messages. Although it is possible to develop quite sophisticated applications with just the Series 3a and its built-in OPL tools, I strongly advise a PC-hosted OPL/g development kit. Not only does it provide access to better editors and additional tools, but the bulging folder of documentation is superior to the less detailed programming manual supplied with every 3a. The OPL/g kit offers a complete OPL development system which only lacks a PC-hosted 3a emulator (an old unsupported Series 3 emulator is freely available, but is of little use for 3a work). The following OPL code gives a feel for the ease with which you can access some of the features of the Series 3a. The resulting execution is shown in Figures 7 and 8: PROC watch: REM based on the demo from the Psion manual LOCAL k%,s%,sec%,min% FONT 11,16 REM put up a little splash dialog (Fig 7) dINIT "Stopwatch" REM the title dTEXT "","A demo of OPL",$2 REM the text dTEXT "","for PIE Developers",$302 dBUTTONS "",13 REM close by pressing the Enter key DIALOG REM actually puts the dialog up AT 20,1 :PRINT "Stopwatch" AT 15,11 :PRINT "Press a key to start" GET REM wait for keypress DO REM our main loop CLS :min%=0:sec%=0:s%=SECOND AT 15,11 :PRINT " S=Stop, L=Lap " loop:: REM a label k%=KEY AND $ffdf REM ensures upper case IF k%=%S REM user pressed the S key GOTO pause:: ENDIF IF k%=%L REM user pressed the L key AT 20,6 :PRINT "Lap: ";min%;":"; IF sec%<10 :PRINT "0"; :ENDIF PRINT sec%;" "; ENDIF IF SECOND<>s% s%=SECOND :sec%=sec%+1 IF sec%=60 :sec%=0:min%=min%+1 :ENDIF AT 17,8 PRINT "Mins",min%,"Secs", IF sec%<10 :PRINT "0"; :ENDIF PRINT sec%;" "; ENDIF GOTO loop:: pause:: REM displays status message GIPRINT "Paused",3 mINIT REM set up a menu mCARD "Stopwatch","Restart",%r,"Zero",%z,"Exit",%x REM mCARD sets the menu title to Stopwatch REM with the other three items as REM commands within the menu (Fig 8). Key commands REM are the letters given, e.g. REM %r means the r key k%=MENU REM display the menu and return the result IF k%=%r REM user pressed the r key REM displays status message for 2 sec GIPRINT "Restarted",3 GOTO loop:: ENDIF GIPRINT "Zeroed",3 UNTIL k%<>%z REM end of DO ENDP Intermediate C Tools Included in the Psion Developer's kit are the Clarion/JPI Topspeed C compiler, three hefty ring-bound files of Psion-specific documentation, and additional disks containing Psion's libraries, tools and example code. Installation consists of a simple procedure to put the Topspeed environment on your hard disk, followed by the straightforward addition of Psion material. Armed with a PC running only MS-DOS, and 11.5 MByte of free disk space, you can get the environment up and running quickly. The only extra components which you need are a Series 3a and a serial link to connect it to your PC. Even the PC is not mandatory. For the purposes of this review, I installed the C-based kit on a Power Mac 6100/60 with 16 MByte of RAM, running SoftWindows on a 30 MByte virtual disk, and with the Mac serial connection kit. This ran sweetly throughout, and I encountered no compatibility problems; indeed, it let me use Alpha, an outstanding shareware text editor for the Mac. Those condemned to less pleasurable hardware might want to use Brief, which is used in-house by Psion themselves (Topspeed comes with its own integrated text editor as well). Psion development in C is restricted to the Topspeed compiler and linker conventions. Those tempted to try to use other compilers are clearly warned that EPOC and the Psion libraries require strict adherence to the small code and data model, which spares segment registers. Although Psion are keen to remove this restriction, it remains for the time being. While this may bring disappointment to those yearning to work in Visual C++, for example, the Clarion/JPI product is quite pleasant in use, and should not be condemned out of hand. Hello Psion The following two versions of the ever popular "Hello World" program illustrate different flavors of C development, the first using a Console window: /* Using PLIB for Console I/O*/ #include GLDEF_C INT main(VOID) { p_printf("Hello World!"); /* print msg to Console */ p_getch(); /* wait for a keypress */ return(0); } /* Using PLIB and WLIB window server for console I/O */ #include #include GLDEF_C INT main(VOID) { WS_EV event; wStartup(); /* start up the window server */ gPrintText(10,20,"Hello World!",12); /* call the window server to print the message */ do /* then wait for a keypress event */ {wGetEventWait(&event);} while (event.type!=WM_KEY); return(0); } Using the more sophisticated facilities of HWIF, this might become: #include #include #include /*first, define the menus */ LOCAL_D TEXT *cmds[]= /* these are the contents of the single menu */ { "nNull", "xExit", NULL }; LOCAL_D H_MENU_DATA mdata[]= /* this defines the single Special menu */ { "Special",2, NULL }; /* C magic to define _cmds and _mdata from above */ GLDEF_D TEXT ** _cmds=(cmds[0]); GLDEF_D H_MENU_DATA * _mdata=(&mdata[0]); LOCAL_D UNIT MainWid; /* to hold the main window */ LOCAL_C VOID ManageCommand(INT keycode) /* a simple skeletal command manager */ { INT index; TEXT buf[40]; switch (keycode) { case 'x': /* only really handles EXIT */ p_exit(0); default: /* otherwise, display an info msg */ index=uLocateCommand(keycode); if (index>=0) { p_atos(&buf[0],"You chose '%s'",cmds[index]+1); wInfoMsg(&buf[0]); } } } LOCAL_C VOID MainLoop(VOID) /* generic event loop; assumes an EXIT menu command */ { INT ret; WMSG_KEY key; FOREVER { uGetKey(&key); /* get keypress */ if (key.keycode&W_SPECIAL_KEY) /* handle menu shortcut */ ManageCommand(key.keycode&(~SPECIAL_KEY)); else if (key.keycode==W_KEY_MENU && !(key.modifiers&W_CTRL_MODIFIER)) /* handle menu shortcut when menu bar is shown */ { ret=uPresentMenus(); if (ret>0) ManageCommand(ret); } } } LOCAL_C VOID ReduceScreenSize(VOID) { W_WINDATA wd; wd.extent.tl.x=wd.extent.tl.y=0; /* top left=(0,0) */ wd.extent.width=189; wd.extent.height=80; /* set the window to 3/3a-compatible size */ wSetWindow(MainWid,W_WIN_EXTENT,&wd); /* check for errors by flushing the call first */ if (uErrorValue(wCheckPoint())) p_exit(0); } LOCAL_C VOID CreateGC(VOID) /* initializes the graphics context */ { INT hgc; hgc=gCreateGC0(MainWid); /* initialize graphics context with default characteristics, for the window which was generated by the uCommonInit() call */ if (hgc<0) /* handle failures */ p_exit(hgc); } LOCAL_C VOID SpecificInit(VOID) { /* find window generated by uCommonInit() call */ MainWid=uFindMainWid(); /* resize the main graphics window as above */ ReduceScreenSize(); /* call graphics context init above */ CreateGC(); /* perform standard framing */ gBorder(W_BORD_CORNER_4); /* display permanent status window */ wsEnable(); wInfoMsg("Hello World!"); /* display message */ } GLDEF_C VOID main(VOID) { /* perform essential common initialization */ uCommonInit(); /* perform app-specific init above */ SpecificInit(); MainLoop(); /* run the event loop above */ } Compare these with the object-oriented example in the next section. Object-Oriented Programming in C Because of the combination of JPI's C compiler and the 3a's ROM, the OOP on the 3a involves a complex system of different C and non-C source files. This may at first seem to flaunt trends towards C++ as a universal commercial standard, and those who are sensitive to the aesthetics of language may be shocked. In practice, however, it is a good solution - there are many good points relative to the disadvantages. One of the weaknesses of this solution is the distinct lack of elegance in calling object methods in Psion's OOP C. It requires using an indirect generic method dispatch function, rather than an inherent direct call, and looks very ugly. It is a result of the normally unseen mechanics of method despatch being laid bare - an advantage for compactness and efficiency at the cost of the programmer interface. Class and method definitions are more polished and almost conventional relative to other OO languages. Class definitions are put in a category file which is distinguished by the extension ".CAT". Here's a nonfunctional tutorial example which also illustrates a number of characteristics of Psion's OOP C. For the sake of clarity, comments are preceded by a "+" sign, although this is not necessary in practice. +A nonfunctional category file example IMAGE piedemo +generates an app, not a LIBRARY EXTERNAL olib +external ref to the OLIB obj library INCLUDE p_std.h INCLUDE p_object.h +standard includes INCLUDE varray.h +special include for VAFLAT class CLASS demo root +define class DEMO w/ ROOT superclass +the formal class definition { +first the methods REPLACE destroy +replace inherited DESTROY with my own ADD dm_init +add new method to create VAFLAT obj DEFER dm_sub +add a deferred method, which +subsclasses are required to define CONSTANTS +symbolic constants { +a buffer size DEMO_BUF_SIZE 128 DEMO_VOBJ 16 +size of the VAFLAT object } TYPES +structures { typedef struct /* you have to use C-style comments here since structs are output direct */ { TEXT *buf; UWORD len; } DEMO_BUF; } PROPERTY 1 +define fields/'property' of the class { PR_VAFLAT *array; +instance of the VAFLAT class DEMO_BUF buffer; +a buffer } } CLASS sub demo +now, subclass the DEMO class { REPLACE dm_sub +replace deferred method as required } REQUIRE moredemo +include sub-category file moredemo.cl Using the DOS batch files and utilities provided, a skeletal C source code file to contain method implementations is generated. Each method implementation is of the form: #pragma METHOD_CALL METHOD VOID demo_destroy(PR_SUB *self) { /* here, you simply insert the code */ } Although executable applications and other files do not have the Mac's data and resource forks, Psion encourages the use of structured resource files within source code. This not only helps with localization to different languages - a process which is vital given the 3a's strong user base across multilingual Europe - but is also makes development much easier (in the same way using include files does). Here are excerpts from such a resource file, recognized by its extension ".RSS": #include /* HWIM resource definitions */ #include /* ditto for dialogs esp. */ #include /* generated in pre-compilation */ RESOURCE WSERV_INFO demo_accs /*required 1st RSS */ { menbar_id=demo_menbar; /* refers to MENU_BAR RSS */ first_com=O_COM_EXIT; /* set to a method method # /* /* of the application's command manager */ accel={'x'}; /* defines 1/ more accelerator keys /* /* (command key equivalents) */ } RESOURCE MENU_BAR demo_menbar /* define contents of */ { /* the application's menu bar */ items= { MENU_BAR_ITEM { menu_id=special_menu; mb_item="Special"; /* define Special menu */ } } } RESOURCE MENU special_menu { items= { MENU_ITEM { com_id=O_COM_EXIT; mn_item="Exit"; /* define a single item in */ } } } /* the Special menu */ RESOURCE DIALOG demo_dialog { flags=DLGBOX_NO_DDP; /* a simple dialog box */ title="A dialog"; /* the dialog's title */ controls= { CONTROL { class=C_TEXTWIN; /* centre this item and disable it */ flags=DLOGBOX_ITEM_CENTRE|DLGBOX_ITEM_DEAD; info=TXTMESS { flags=IN_TEXTWIN_AL_CENTRE; str="A text string"; }; }, CONTROL { class=C_ACLIST; info=ACLIST { rid=-SYS_AC_CONTINUE; /* the one button action list to dismiss */ } } } } /* the dialog, defined in hwim.rh */ Objects are created (that is, a class is instantiated) using one of six functions such as p_new, which returns a handle used to identify the object. The handle is a pointer to a heap cell containing the property of that class, initialized with zeros. Within the methods of that class, the object's handle is conventionally referred to as self. There is no support for private or protected properties or methods. Once created, objects support message passing (the invocation of the object's methods) using a range of different functions such as p_sendn, which take as their first two parameters the object handle and the number of the method to be called. Because methods are numbered using bytes, no class may have more than 256 methods, including those that are inherited; by convention, method 0 is the DESTROY method. Functions are provided which support the sending of messages to more specific targets: these can search the superclass chain of an object (p_supersend), or a specific class within the superclass chain (p_exactsend). No function to call a method supports the passing of more than three parameters in addition to the object and method number. Object destruction is performed by the DESTROY method, which must also destroy all its components such as component objects (other objects which are properties of that class), and their components (and so on). The only exception to this is objects which exist at the time that an application terminates: EPOC sees to any cleaning up required to release the resources used by the process. The flavor of these techniques can be illustrated by the main() function of an application which uses the HWIM library: #include GLDEF_C VOID main(VOID) { IN_HWIMMAN app;IN_WSERV ws; VOID *handle; p_linklib(0); /* this dynamically links the application category with DYLs in the ROM */ app.flags= FLG_APPMAN_RSCFILE| FLG_APPMAN_SRSCFILE|FLG_APPMAN_CLEAN; /* specifies options during the initialization of the application manager; here, specifying that the app uses the system resource file, an app resource file, and a CLEANUP object. These flags are mandatory for HWIM apps */ app.wserv_cat=p_getlibh(CAT_MYAPP_MYAPP); /* sets the cat field of the IN_HWIMMAN struct to the category of the app's window server object. p_getlibh is a PLIB function used to return the category handle for a given category number*/ app.wserv_class=C_MYAPPWS; /* sets the class field to the class number of the app's window server object */ ws.com_cat=p_getlibh(CAT_MYAPP_HWIM); /* sets the cat field of the IN_WSERV struct to the category of the app's command manager*/ ws.com_class=C_COMMAN; /* sets the class field to the class number of the app's command manager*/ handle=p_new(CAT_MYAPP_HWIM,C_HWIMMAN); /* creates the app's command manager as an instance of the HWIMMAN class*/ p_send4(handle,O_AM_INIT,&app,&ws); /* sends the AM_INIT message to the app's cmd mgr, which inits it w/o returning, starting the app */ } Categories are classes which are grouped into a load module which is loaded into a single code segment. Because they are shared code segments, only one copy of a category is in memory, no matter how many different processes are executing code from it. They include image categories which are used to implement programs, and dynamic libraries (DYLs) which include much of the ROM and any additional material to assist in the development of larger and more complex applications. Given the main() function just discussed, a simple window-based "Hello World" application can be implemented with just three methods: #pragma METHOD_CALL /* ensures right call convention*/ METHOD VOID hellows_ws_dyn_init(PR_HELLOWS *self) /* simply creates and initializes a bordered window*/ { self->wserv.cli=f_new(CAT_HELLO_HELLO,C_HELLOBW); /* create an instance of the HELLOBW bordered window, and set it to be the app's client window*/ p_send2(self->wserv.cli,O_WN_INIT); /* initalize the window by calling the method below*/ } METHOD VOID hellobw_wn_init(PR_HELLOBW *self) /* the initialization method for the bordered window*/ { W_WINDATA wd; wd.extent.tl.x=0; wd.extent.tl.y=0; /* set the top left of the window to (0,0)*/ wd.extent.width=wserv_channel->conn.info.pixels.x; wd.extent.height=wserv_channel->conn.info.pixels.y; /* set the window size to the screen dimensions, which are read from 'magic' static wserv_channel*/ p_send5(self,O_WN_CONNECT,NULL,W_WIN_EXTENT,&wd); /* connect to the window as a top-level window*/ p_send3(self,O_WN_VISIBLE,WV_INITVIS); /* make the window visible*/ p_send3(self,O_WN_EMPHASISE,TRUE); /* set the window to the emphasized state*/ } METHOD VOID hellobw_wn_draw(PR_HELLOBW *self) /* a draw method for window, called by system code*/ { p_supersend2(self,O_WN_DRAW); /* first, call the inherited drawing method to draw the border, etc.*/ gPrintText(50,50,"Hello World!",11); /* then print the message, using the window server function gPrintText()*/ } The Psion Class Library The Psion class library is substantial and very capable; indexes covering over 180 classes are provided on the source code disk for this issue of PDA Developers. It is clearly not possible here to provide any meaningful detail of these riches, but the following listing of functional areas may give an idea of the breadth of coverage: * commands and menus * windows, dialogs, dialog controls * active objects and asynchronous requests * error handling and recovery * files and file lists * printing * copying and pasting * time and timers * segmented buffers * variable length arrays * resources * system services * inter-process communication. Inevitably, many classes are devoted to the support of the user interface. The range of dialog controls available is particularly wide, including specific subclasses to handle the entry of almost any data type, from numeric ranges to latitude and longitude. The EDWIN edit window class is unusually sophisticated - it provides multiline editing windows which handle cursor movement, selection, typing and deletion, with vertical and horizontal scrolling, word wrapping and support for common editing commands such as copy, insert, find and replace. Among the more fundamental classes, those offering different varieties of variable length arrays are worth mentioning. They implement arrays of a variable number of records, which can be of fixed or variable length and are dynamically allocated from the heap. Some classes facilitate this by letting you preset the size, minimizing the risk of failure due to lack of memory. Debugging C Applications A C source level debugger, which uses symbol table information generated by the Clarion/JPI compiler, is provided. The Psion Series 3a can be tethered to the desktop development system using a serial link cable, in order to debug a remote process, or the debugger application can be run locally in emulation. You can perform remote debugging using a PC and the PC Link kit. It even works satisfactorily over a Mac Link with the debugger hosted by SoftWindows on a Power Mac (although the PC mouse emulation is not quite perfect, oddly restricting mouse movement to the upper half of the screen). This is a high quality, conventional source debugger of the type commonly found in professional development systems. It supports process loading and running, breakpoints, trace, step and run, and displays process, segment, device, and environment variable list windows, together with the main process view. It can also show the contents of files. Within the main process debugging view, there are subviews containing code, segment, register, stack, symbol, variable, file and magic static variable information. Although there is no specific support for object-level debugging, in all other respects the debugger's features appear to satisfy even the most demanding of users. The debugger can also be used to bring a process running on a tethered 3a under control, or to locate a "panic" (Psion's delightful term for an error which has penetrated to the system error handler) in a running process. There is also a separate process spy which can be run on the 3a as an aid to debugging applications written in OPL or C. The Future Psion's future technology, expounded as being a better alternative to handwriting recognition, and presaged by the 3a's digital audio recording, is voice recognition. Although Psion has made considerable advances in this area, it does not address the most prominent shortcoming in the 3a's otherwise impressive capabilities - the lack of drawing. Existing voice recognition systems also suffer from a number of problems which have yet to be overcome. These amount of the difficulty in distinguishing voice data from background noise, whether it's nonspecific or contains confusing data (like someone else's voice, or non-data messages from the user). Whether the effort and investment required to address these and other obvious issues ever return a product which can compete with the 3a or Newton remains to be seen; it is undoubtedly high risk. There is an unfortunate tendency among many innovative corporations to deliberately avoid embracing technologies developed by competing innovators, and those which they claim that they are outclassing or superseding. It would be a great shame if Psion was to ignore the strengths of stylus drawing in their bid to make voice input practical. Whatever may become of the latter, many palmtop users need sketching abilities, and these should be supported in the next Psion model. The same applies to the likes of electronic books (see Figure 9), another great strength of the Newton which has not yet been addressed on the Psion Series 3a. Conclusions Although there are a few remaining niggles, Psion has done exceptionally well in the design of the Series 3a. Its instant usability is a very strong selling point, enabling potential purchasers to try it out before purchase, and sales staff to show it off with ease. No matter how advanced the technology within a palmtop computer, if it's difficult to sell and its functionality obscured or compromised, then the Psion Series 3a and its successors will always be very competitive. Given strong historical and expected sales, the Series 3a is a good choice of platform for which to develop. It is hard to estimate future sales, but it is likely that less than 10% of the 3a's potential market has even heard of the product yet. It's capable of supporting with ease at least another 30 or 40 horizontal market software products. You need to bear in mind that the great majority of users are likely only to see the 3a as a personal information manager, and are therefore neither actively seeking third-party products nor likely to purchase overly complex software. Psion's friendly and open approach to developer support sets a good example to the industry, and will help you all the way from inception to marketing. Although development systems may not appear as polished as those in which Apple has invested millions of dollars, you should not overlook the relative ease with which very good applications can be written in OPL (see Figure 10), nor the immense richness of Psion's OO class library. The complete cost of a development system is modest by any standards, and Psion's business model does not rely on their charging you royalties on your products. Look in future issues of PDA Developers for further articles covering Psion development. The product is good if not outstanding, it is selling better than any other palmtop or PDA and there is no surfeit of third party products. What are you waiting for? Further Information Developer kits and information can be obtained from Psion at 508.371.0310 (Concord, MA), 415.951.4764 (San Francisco, CA), 312.419.5300 (Chicago, IL) and 071.262.5580 (London, UK). Psion technical staff provide extensive free support on the CompuServe Palmtop Forum (GO PALMTOPA, section 7, Psion Inc.), the Internet newsgroup (comp.sys.psion), and the UK conferencing system CIX (in the psion conference). There are two third-party books which cover various aspects of OPL programming: First Steps in Programming the Psion Series 3 by Mike Shaw (Kuma, ISBN 0-7457-0145-0), and Serious Programming on the Psion Series 3 by Bill Aitken (Kuma, ISBN 0-7457-0035-7). Definitive documentation is presented in the Psion reference manuals, and in electronically available digests such as the Clive Feather's Psionics files [which can be found on this issue's source code disk].